home *** CD-ROM | disk | FTP | other *** search
- /*$T vertex.c GC 1.137 08/09/02 17:47:18 */
-
- /*$6
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- */
-
- #include "zgl.h"
-
- /* */
-
- void glopNormal(GLContext *c, GLParam *p) {
- V3 v;
- /*~~*/
-
- v.X = p[1].f;
- v.Y = p[2].f;
- v.Z = p[3].f;
-
- c->current_normal.X = v.X;
- c->current_normal.Y = v.Y;
- c->current_normal.Z = v.Z;
- c->current_normal.W = 0;
- }
-
- /* */
- void glopTexCoord(GLContext *c, GLParam *p) {
- c->current_tex_coord.X = p[1].f;
- c->current_tex_coord.Y = p[2].f;
- c->current_tex_coord.Z = p[3].f;
- c->current_tex_coord.W = p[4].f;
- }
-
- /* */
- void glopEdgeFlag(GLContext *c, GLParam *p) {
- c->current_edge_flag = p[1].i;
- }
-
- /* */
- void glopColor(GLContext *c, GLParam *p) {
- c->current_color.X = p[1].f;
- c->current_color.Y = p[2].f;
- c->current_color.Z = p[3].f;
- c->current_color.W = p[4].f;
- c->longcurrent_color[0] = p[5].ui;
- c->longcurrent_color[1] = p[6].ui;
- c->longcurrent_color[2] = p[7].ui;
-
- if(c->color_material_enabled) {
- GLParam q[7];
- q[0].op = OP_Material;
- q[1].i = c->current_color_material_mode;
- q[2].i = c->current_color_material_type;
- q[3].f = p[1].f;
- q[4].f = p[2].f;
- q[5].f = p[3].f;
- q[6].f = p[4].f;
- glopMaterial(c, q);
- }
- }
-
- /* */
- void gl_eval_viewport(GLContext *c) {
- GLViewport *v;
- float zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS));
-
- v = &c->viewport;
-
- v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin;
- v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin;
- v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2;
-
- v->scale.X = (v->xsize - 0.5) / 2.0;
- v->scale.Y = -(v->ysize - 0.5) / 2.0;
- v->scale.Z = -((zsize - 0.5) / 2.0);
- }
-
- /* */
- void glopBegin(GLContext *c, GLParam *p) {
- int type;
- M4 tmp;
-
- assert(c->in_begin == 0);
-
- type = p[1].i;
- c->begin_type = type;
- c->in_begin = 1;
- c->vertex_n = 0;
- c->vertex_cnt = 0;
-
- if(c->matrix_model_projection_updated) {
- if(c->lighting_enabled) {
- /* precompute inverse modelview */
- gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]);
- gl_M4_Transpose(&c->matrix_model_view_inv, &tmp);
- }
- else {
- float *m = &c->matrix_model_projection.m[0][0];
-
- /* precompute projection matrix */
- gl_M4_Mul(&c->matrix_model_projection, c->matrix_stack_ptr[1], c->matrix_stack_ptr[0]);
-
- /* test to accelerate computation */
- c->matrix_model_projection_no_w_transform = 0;
- if(m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) {
- c->matrix_model_projection_no_w_transform = 1;
- }
- }
-
- /* test if the texture matrix is not Identity */
- c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]);
-
- c->matrix_model_projection_updated = 0;
- }
-
- /* viewport */
- if(c->viewport.updated) {
- gl_eval_viewport(c);
- c->viewport.updated = 0;
- }
-
- /* triangle drawing functions */
- if(c->render_mode == GL_SELECT) {
- c->draw_triangle_front = gl_draw_triangle_select;
- c->draw_triangle_back = gl_draw_triangle_select;
- }
- else {
- switch(c->polygon_mode_front) {
- case GL_POINT: c->draw_triangle_front = gl_draw_triangle_point; break;
- case GL_LINE: c->draw_triangle_front = gl_draw_triangle_line; break;
- default: c->draw_triangle_front = gl_draw_triangle_fill; break;
- }
-
- switch(c->polygon_mode_back) {
- case GL_POINT: c->draw_triangle_back = gl_draw_triangle_point; break;
- case GL_LINE: c->draw_triangle_back = gl_draw_triangle_line; break;
- default: c->draw_triangle_back = gl_draw_triangle_fill; break;
- }
- }
- }
-
- /*
- * coords, tranformation , clip code and projection £
- * TODO:: handle all cases
- */
- static inline void gl_vertex_transform(GLContext *c, GLVertex *v) {
- float *m;
- V4 *n;
-
- if(c->lighting_enabled) {
- /* eye coordinates needed for lighting */
- m = &c->matrix_stack_ptr[0]->m[0][0];
- v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]);
- v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]);
- v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]);
- v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]);
-
- /* projection coordinates */
- m = &c->matrix_stack_ptr[1]->m[0][0];
- v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] + v->ec.Z * m[2] + v->ec.W * m[3]);
- v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] + v->ec.Z * m[6] + v->ec.W * m[7]);
- v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] + v->ec.Z * m[10] + v->ec.W * m[11]);
- v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] + v->ec.Z * m[14] + v->ec.W * m[15]);
-
- m = &c->matrix_model_view_inv.m[0][0];
- n = &c->current_normal;
-
- v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]);
- v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]);
- v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]);
-
- if(c->normalize_enabled) {
- gl_V3_Norm(&v->normal);
- }
- }
- else {
- /*
- * no eye coordinates needed, no normal £
- * NOTE: W = 1 is assumed
- */
- m = &c->matrix_model_projection.m[0][0];
-
- v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]);
- v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]);
- v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]);
- if(c->matrix_model_projection_no_w_transform) {
- v->pc.W = m[15];
- }
- else {
- v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]);
- }
- }
-
- v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W);
- }
-
- /* */
- void glopVertex(GLContext *c, GLParam *p) {
- GLVertex *v;
- int n, i, cnt;
-
- assert(c->in_begin != 0);
-
- n = c->vertex_n;
- cnt = c->vertex_cnt;
- cnt++;
- c->vertex_cnt = cnt;
-
- /* quick fix to avoid crashes on large polygons */
- if(n >= c->vertex_max) {
- GLVertex *newarray;
- c->vertex_max <<= 1; /* just double size */
- newarray = malloc(sizeof(GLVertex) * c->vertex_max);
- if(!newarray) {
- gl_fatal_error("unable to allocate GLVertex array.\n");
- }
-
- memcpy(newarray, c->vertex, n * sizeof(GLVertex));
- free(c->vertex);
- c->vertex = newarray;
- }
-
- /* new vertex entry */
- v = &c->vertex[n];
- n++;
-
- v->coord.X = p[1].f;
- v->coord.Y = p[2].f;
- v->coord.Z = p[3].f;
- v->coord.W = p[4].f;
-
- gl_vertex_transform(c, v);
-
- /* color */
- if(c->lighting_enabled) {
- gl_shade_vertex(c, v);
- }
- else {
- v->color = c->current_color;
- }
-
- /* tex coords */
- if(c->texture_2d_enabled) {
- if(c->apply_texture_matrix) {
- gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord);
- }
- else {
- v->tex_coord = c->current_tex_coord;
- }
- }
-
- /* precompute the mapping to the viewport */
- if(v->clip_code == 0) {
- gl_transform_to_viewport(c, v);
- }
-
- /* edge flag */
- v->edge_flag = c->current_edge_flag;
-
- switch(c->begin_type) {
- case GL_POINTS:
- gl_draw_point(c, &c->vertex[0]);
- n = 0;
- break;
-
- case GL_LINES:
- if(n == 2) {
- gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
- n = 0;
- }
- break;
- case GL_LINE_STRIP:
- case GL_LINE_LOOP:
- if(n == 1) {
- c->vertex[2] = c->vertex[0];
- }
- else if(n == 2) {
- gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
- c->vertex[0] = c->vertex[1];
- n = 1;
- }
- break;
-
- case GL_TRIANGLES:
- if(n == 3) {
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
- n = 0;
- }
- break;
- case GL_TRIANGLE_STRIP:
- if(cnt >= 3) {
- if(n == 3) {
- n = 0;
- }
-
- /* needed to respect triangle orientation */
- switch(cnt & 1) {
- case 0:
- gl_draw_triangle(c, &c->vertex[2], &c->vertex[1], &c->vertex[0]);
- break;
- default:
- case 1:
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
- break;
- }
- }
- break;
- case GL_TRIANGLE_FAN:
- if(n == 3) {
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
- c->vertex[1] = c->vertex[2];
- n = 2;
- }
- break;
-
- case GL_QUADS:
- if(n == 4) {
- c->vertex[2].edge_flag = 0;
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
- c->vertex[2].edge_flag = 1;
- c->vertex[0].edge_flag = 0;
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]);
- n = 0;
- }
- break;
-
- case GL_QUAD_STRIP:
- if(n == 4) {
- gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
- gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
- for(i = 0; i < 2; i++) {
- c->vertex[i] = c->vertex[i + 2];
- }
-
- n = 2;
- }
- break;
- case GL_POLYGON:
- break;
- default:
- gl_fatal_error("glBegin: type %x not handled\n", c->begin_type);
- }
-
- c->vertex_n = n;
- }
-
- /* */
- void glopEnd(GLContext *c, GLParam *param) {
- assert(c->in_begin == 1);
-
- if(c->begin_type == GL_LINE_LOOP) {
- if(c->vertex_cnt >= 3) {
- gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
- }
- }
- else if(c->begin_type == GL_POLYGON) {
- int i = c->vertex_cnt;
- while(i >= 3) {
- i--;
- gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]);
- }
- }
-
- c->in_begin = 0;
- }
-